package com.sghd.candy.module.rank.service;

import com.sghd.candy.module.fight.manager.FightInfo;
import com.sghd.candy.module.fight.service.FightService;
import com.sghd.candy.module.player.manager.Player;
import com.sghd.common.ramcache.orm.Querier;
import com.sghd.common.scheduler.Scheduled;
import com.sghd.pojo.candy.rank.RankItem;
import com.sghd.pojo.candy.rank.RankList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author frank
 * @date 2019-01-17 15:24
 * @desc
 **/
@Component
public class RankService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private Querier querier;

    /** 积分榜*/
    private CopyOnWriteArrayList<RankItem> gradeList = new CopyOnWriteArrayList<>();

    /** 胜率榜*/
    private CopyOnWriteArrayList<RankItem> winRateList = new CopyOnWriteArrayList<>();

    private ReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock readLock = lock.readLock();
    private Lock writeLock = lock.writeLock();
    @Autowired
    private FightService fightService;

    @PostConstruct
    void init() {
        refresh();
    }

    @Scheduled(name = "refreshRank", value = "0 0 */2 * * ?")
    public void refresh() {
        writeLock.lock();
        if (!gradeList.isEmpty()) {
            gradeList.clear();
        }
        if (!winRateList.isEmpty()) {
            winRateList.clear();
        }
        try {
            List<Object[]> gradeResult = querier.list(FightInfo.class, Object[].class, FightInfo.RANK_BY_GRADE);
            for (Object[] objects : gradeResult) {
                gradeList.add(RankItem.valueOf(((BigInteger) objects[0]).longValue(), (String) (objects[3]),
                        (int) (objects[4]), (int) (objects[2]), (float) (objects[1])));
            }
            List<Object[]> winRateResult = querier.list(FightInfo.class, Object[].class, FightInfo.RANK_BY_WINRATE);
            for (Object[] objects : winRateResult) {
                winRateList.add(RankItem.valueOf(((BigInteger) objects[0]).longValue(), (String) (objects[3]),
                        (int) (objects[4]), (int) (objects[2]), (float) (objects[1])));
            }
        } catch (Exception e) {
            logger.error("刷新排行数据发生未知错误！", e);
        } finally {
            writeLock.unlock();
        }
        logger.debug("排行榜数据更新！");
    }

    public RankList getRank(Player player) {
        readLock.lock();
        try {
            FightInfo fightInfo = fightService.load(player);
            int pvpCount = fightInfo.getPvpCount();
            int pvpWin = fightInfo.getPvpWin();
            float rate = 0.0f;
            if (pvpCount != 0) {
                rate = (float) (pvpWin * 1.0 / pvpCount);
                BigDecimal decimal = new BigDecimal(rate);
                rate = decimal.setScale(3, BigDecimal.ROUND_HALF_UP).floatValue();
            }
            List<RankItem> gradeList = new ArrayList<>();
            for (RankItem rankItem : this.gradeList) {
                gradeList.add(rankItem.copy());
            }
            List<RankItem> winRateList = new ArrayList<>();
            for (RankItem rankItem : this.winRateList) {
                winRateList.add(rankItem.copy());
            }
            return RankList.valueOf(player.getPlayerId(), fightInfo.getPvpGrade(), rate, gradeList, winRateList);
        } finally {
            readLock.unlock();
        }
    }
}
